package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.FreezeInfoApi;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.domain.FreezeInfo;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MovementsService {
    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private CommentApi commentApi;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private MqMessageService mqMessageService;

    @DubboReference
    private FreezeInfoApi freezeInfoApi;

    //保存
    public void movements(String textContent, MultipartFile[] imageContent, String location, String latitude, String longitude) throws IOException {
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        if (userInfo.getUserStatus().equals("2")) {
            //根据userId查询冻结信息
            FreezeInfo freezeInfo = freezeInfoApi.findByUserId(userId);
            if (freezeInfo.getFreezingRange() == 3) {
                throw new BusinessException(new ErrorResult("99999", "你已被禁止发布动态"));
            }
        }
        Movement movement = new Movement();
        movement.setUserId(UserHolder.getUserId());
        movement.setTextContent(textContent);
        movement.setCreated(System.currentTimeMillis());
        movement.setLongitude(longitude);
        movement.setLatitude(latitude);
        movement.setLocationName(location);
        List<String> mediasList = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String url = ossTemplate.upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename());
            mediasList.add(url);
        }
        movement.setMedias(mediasList);

        //调用api进行保存
        String movementId = movementApi.save(movement);

        //发送MQ消息，用于动态审核
        mqMessageService.sendAudiMessage(movementId);
    }

    // 查询用户全部动态
    public PageResult all(Integer page, Integer pageSize, Long userId) {
        //1. 根据userID查询动态信息集合
        List<Movement> movements = movementApi.findUserId(userId, page, pageSize);
        //2. 判断集合是否为空
        if (movements == null) {
            return new PageResult();
        }
        //3. 如集合不为空
        //3.1 查询出动态发布人的信息
        UserInfo userInfo = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        //3.2 遍历动态信息集合，给动态添加上动态发布人的信息
        for (Movement movement : movements) {
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //3.2.1 从redis中查询点赞状态，如果有点赞状态，设置为1
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY + vo.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            if (hasKey) {
                vo.setHasLiked(1);
            }
            //3.2.1 从redis中查询喜欢状态，如果有点喜欢态，设置为1
            String loveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            Boolean hasLoveKey = redisTemplate.opsForHash().hasKey(redisKey, loveKey);
            if (hasLoveKey) {
                vo.setHasLoved(1);
            }
            vos.add(vo);
        }
        return new PageResult(page, pageSize, 0l, vos);
    }

    //查询好友动态
    public PageResult findFriendId(Integer page, Integer pageSize) {
        //1. 先获取，当前用户的id
        Long friendId = UserHolder.getUserId();
        //2. 调用api的方法，查询出动态信息来
        List<Movement> movements = movementApi.findByFriendId(friendId, page, pageSize);
        //3. 返回数据
        return initPage(movements, page, pageSize);
    }

    //公共的方法
    private PageResult initPage(List<Movement> list, Integer page, Integer pagesize) {
        //3、判断动态列表是否为空
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //一次性，将list中所有的动态发布人查询出来
        //a：提取list中的所有动态发布人id
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);//list，属性名，类型
        //b：调用UserInfoApi，查询多个用户的用户信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds);
        //4、循环List<Movement>，一个Movement构建一个MovementVo对象
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            Long userId = movement.getUserId();//获取动态发布人
            UserInfo info = map.get(userId); //直接从map获取
            //UserInfo info = userInfoApi.findById(userId);//查询动态发布人的信息
            //调用MovementsVo工具方法init构建
            MovementsVo vo = MovementsVo.init(info, movement);//用户信息，动态详情
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY + vo.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            if (hasKey) {
                vo.setHasLiked(1);
            }
            vos.add(vo);
        }
        //5、返回
        return new PageResult(page, pagesize, 0l, vos);
    }

    //动态推荐
    public PageResult findByRecommend(Integer page, Integer pageSize) {
        Long userId = UserHolder.getUserId();
        String key = "MOVEMENTS_RECOMMEND_" + userId;
        String value = redisTemplate.opsForValue().get(key);

        List<Movement> list = new ArrayList<>();
        //判断是否有数据
        if (StringUtils.isNotEmpty(value)) {
            //1. 非空时
            String[] movementIds = value.split(",");
            list = movementApi.findByMovementIds(movementIds, page, pageSize);
        } else {
            //数据不存在时，调用api随机查询动态列表
            list = movementApi.randomMovement(pageSize);
        }
        return initPage(list, page, pageSize);
    }

    //根据id查询动态
    public MovementsVo findById(String id) {
        Movement movement = movementApi.findById(id);
        Long userId = movement.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        MovementsVo vo = MovementsVo.init(userInfo, movement);
        return vo;
    }

    //点赞
    public Integer like(String id) {
        Integer commentType = 1;//自定义互动类型
        //1. 调用api保存互动数据，更新动态表
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(id));
        comment.setUserId(UserHolder.getUserId());
        comment.setCommentType(commentType);
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.save(comment);
        //2. 将点赞状态，存入Redis（为了方便查询点赞状态）
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        //3. 发送日志消息
        mqMessageService.sendLogMessage(UserHolder.getUserId(), "0203", "log.movement", id); //用户ID，日志类型，路由键，业务id（动态，视频id）
        return count;
    }

    //取消点赞
    public Integer dislike(String id) {
        Integer commentType = 1;
        Long userId = UserHolder.getUserId();
        //1. 调用api删除互动数据，更新动态表
        Integer count = commentApi.delete(commentType, userId, id);
        //2. 删除Redis中的数据
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(redisKey, hashKey);
        return count;
    }

    //喜欢
    public Integer love(String movementId) {
        Integer commentType = 3; //喜欢
        //1、调用API保存
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(commentType);
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.save(comment);
        //2、记录喜欢状态到redis中
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        return count;
    }

    //取消喜欢
    public Integer unlove(String movementId) {
        Integer commentType = 3; //喜欢
        Long userId = UserHolder.getUserId();
        //1、调用API删除互动数据，更新动态表(操作类型，用户id，动态id)
        Integer count = commentApi.delete(commentType, userId, movementId);
        //2、删除redis中的，喜欢状态
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(redisKey, hashKey);
        return count;
    }
}
